package com.hc.acoustics.util

import com.yc.yclibx.exception.YcCalculateException

import java.math.BigDecimal

/**
 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到小数点以后3位，以后的数字四舍五入
 */
object YcCalculator {
    /**
     * 精确的加法运算
     *
     * @param a 被加数
     * @param b 加数
     * @return 两个参数的和
     */
    fun add(a: Double, b: Double): Double {
        val b1 = BigDecimal(a.toString() + "")
        val b2 = BigDecimal(b.toString() + "")
        return b1.add(b2).toDouble()
    }

    /**
     * 精确的减法运算
     *
     * @param a 被减数
     * @param b 减数
     * @return 两个参数的差
     */
    fun subtract(a: Double, b: Double): Double {
        val b1 = BigDecimal(a.toString() + "")
        val b2 = BigDecimal(b.toString() + "")
        return b1.subtract(b2).toDouble()
    }

    /**
     * 提供精确的乘法运算
     *
     * @param a 被乘数
     * @param b 乘数
     * @return 两个参数的积
     */
    fun multiply(a: Double, b: Double): Double {
        val b1 = BigDecimal(a.toString() + "")
        val b2 = BigDecimal(b.toString() + "")
        return b1.multiply(b2).toDouble()
    }

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
     * 定精度，以后的数字四舍五入
     *
     * @param a     被除数
     * @param b     除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    @Throws(YcCalculateException::class)
    @JvmOverloads
    fun divide(a: Double, b: Double, scale: Int = 3): Double {
        if (b == 0.0) {
            throw YcCalculateException("除数不能为0!")
        }
        /*
         * 通过BigDecimal的divide方法进行除法时就会抛异常的，异常如下：
         * java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(Unknown Source)
         * 解决之道：就是给divide设置精确的小数点divide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)
         * BigDecimal.ROUND_HALF_UP : 向（距离）最近的一边舍入，除非两边（的距离）是相等,如果是这样，向上舍入, 1.55保留一位小数结果为1.6
         */
        val b1 = BigDecimal(a.toString() + "")
        val b2 = BigDecimal(b.toString() + "")
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toDouble()
    }

    /**
     * 进行四舍五入
     *
     * @param value 要进行四舍五入的值
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return
     */
    @JvmOverloads
    fun roundOff(value: Double, scale: Int = 2): Double {
        val value1 = BigDecimal(value.toString())
        return value1.setScale(scale, BigDecimal.ROUND_HALF_UP).toDouble()
    }

    fun replaceZero(str: String): String {
        var newS = str
        if (newS.indexOf(".") > 0) {
            newS = newS.replace("0+?$".toRegex(), "")//删掉尾数为0的字符
            newS = newS.replace("[.]$".toRegex(), "")//结尾如果是小数点，则去掉
        }
        return newS
    }
}

